using System.Collections.Generic;

namespace CodeBackpack.Plist
{
    internal class LinkedHashMap<K, V> : MapBase<K, V>
    {
        private readonly IDictionary<K, LinkedListNode<KeyValuePair<K, V>>> map =
            new Dictionary<K, LinkedListNode<KeyValuePair<K, V>>>();
        private readonly LinkedList<KeyValuePair<K, V>> entries = 
            new LinkedList<KeyValuePair<K, V>>();

        public override int Count
        {
            get { return map.Count; }
        }

        public override bool TryGetValue(K key, out V value)
        {
            LinkedListNode<KeyValuePair<K, V>> node;
            bool result = map.TryGetValue(key, out node);
            value = result ? node.Value.Value : default(V);
            return result;
        }

        public override void Add(K key, V value)
        {
            KeyValuePair<K, V> pair = new KeyValuePair<K, V>(key, value);
            LinkedListNode<KeyValuePair<K, V>> node = new LinkedListNode<KeyValuePair<K, V>>(pair);
            map.Add(key, node);
            entries.AddLast(node);
        }

        public override IEnumerator<KeyValuePair<K, V>> GetEnumerator()
        {
            foreach (KeyValuePair<K, V> pair in entries)
            {
                yield return pair;
            }
        }

        public override bool ContainsKey(K key)
        {
            return map.ContainsKey(key);
        }

        public override bool Remove(K key)
        {
            LinkedListNode<KeyValuePair<K, V>> node;
            bool result = map.TryGetValue(key, out node);
            if (result)
            {
                map.Remove(key);
                entries.Remove(node);
            }
            return result;
        }
    }
}